home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Tool Chest / Testing & Debugging / Memory Management / Xap Handles dcmd / Xap.p < prev    next >
Encoding:
Text File  |  1993-09-17  |  7.5 KB  |  193 lines  |  [TEXT/MPS ]

  1. { Zap (Xap): 
  2.     a dcmd to zap the handles and pointers as they are disposed.
  3.     
  4.     Copyright © 1991 by Apple Computer, Inc., all rights reserved.
  5.  
  6.     by     Bo3b Johnson        1/10/91
  7.             MS 37-DS
  8.     for best viewing, use Palatino 12.
  9.     
  10.     5/22/91: Made it version 2 for release to world.
  11.                 Cleaned up comments.
  12.     
  13.     10/9/91: Renamed all files to Xap and changed the makefile 'cuz there are too many 
  14.     lawyers in the world and one of them discovered that someone has a trademark on 
  15.     the name Zap and insisted. The dcmd itself is still named "Zap" 'cuz it has to be.
  16.             –Dave Johnson
  17. }
  18.  
  19. UNIT Zap;
  20.  
  21. (* 
  22.         Build this dude using the Build Menu, it has a make file.
  23.  
  24.         The basic idea here is to trash the blocks in the heap as they are disposed, in order 
  25.         to flush out any use of memory that has been disposed.  This thing will patch the
  26.         traps DisposPtr and DisposHandle, and when they are called, it will fill the entire
  27.         block with $50FFC001 as a funky number that may cause bus errors if used in an 
  28.         inappropriate situation.  As it runs, more and more of the memory will be filled
  29.         with these numbers, so it can also find some use of uninitialized variables.
  30.         
  31.         Notably, you can't really run this during boot time, since the system is a little
  32.         to weird, and a number of Inits do things like dispose the block the pc is running
  33.         out of.  With Zap on, the code stream gets filled with illegal instructions, and you
  34.         find out who is being sick.  (Like a lot of these things, it isn't strictly a bug, since it
  35.         won't crash in the normal case, it's just a bad idea.)
  36.  
  37.         The options are: Zap On|Off
  38.             Off by default, naturally, and it doesn't toggle, although perhaps it should, instead
  39.             of requiring a parameter.
  40.         
  41.         Things to do:
  42.             Could patch the NewPtr/NewHandle side too, to trash the blocks at allocation.
  43.                 That might slow it down too much though.
  44.             Could be restructured a bit to make it easier to figure out, since it started from the
  45.                 leaks source, it has some things that aren't really needed here.
  46.             Are the patches 32 bit clean? I'm not sure if it is cool given the early load time.
  47.             Will it work on Mac+ machines?  LongWord stomping?
  48.             Should patch MultiFinder trap too, to do it's blocks.
  49. *)
  50.  
  51. {$R-}
  52. {$D+}        { debug labels on. }
  53.  
  54. INTERFACE
  55.  
  56.         USES MemTypes, Resources, Traps, Memory, OSUtils, Events,
  57.                     dcmd;                                            { Macsbug interface routines. }
  58.         
  59.  
  60.             { Public declaration for dcmdGlue. Must be in every dcmd. The name cannot be changed. }
  61.         PROCEDURE CommandEntry (paramPtr: dcmdBlockPtr);
  62.  
  63.  
  64. IMPLEMENTATION
  65.  
  66.  
  67.         { They don't
  68.             really have to be globals, but it is a convenience.  I label them with a p, so that you can
  69.             immediately see they are private globals (to this unit), a quality MacApp convention. }
  70.     VAR    pDumpString: Str255;                    { To dump label info, from symbols in code. }
  71.                 
  72. {---------------------------------------------------------------------------------------------------------------------------------}
  73.  
  74.     { Set the address of NewPtr before I patch the trap.  This is so the assembly interface can 
  75.         find this address again, when it is called as part of a NewPtr trap.  This is required because
  76.         I really need PC-relative addressing in order to be able to get this old address.   Both
  77.         of the routines I patch have the same problem, so I have an interface for each.  The
  78.         asm routine just saves off the address passed in, as a PC-Relative variable.  }
  79. PROCEDURE  SetOldDisposPtr (address: LongInt);  EXTERNAL;
  80. PROCEDURE  SetOldDisposHandle (address: LongInt);  EXTERNAL;
  81.  
  82.  
  83.     { The references to the asm routines. }
  84. PROCEDURE WatchDisposPtr;    EXTERNAL;
  85. PROCEDURE WatchDisposHandle;    EXTERNAL;
  86.  
  87.     { When I start up this zapping universe, I have to set the variables used by the
  88.         assembly patch code.  }
  89. PROCEDURE SetActive (state: Boolean);        EXTERNAL;
  90.  
  91.         
  92. {---------------------------------------------------------------------------------------------------------------------------------}
  93.     { This is an init routine that sets up the trap patches, and creates and inits the block in
  94.         the system heap that is used to store the records that track each block I see go by.  This
  95.         is a hard-coded tracking size, which is bad.   This part uses the toolbox, which is a bad
  96.         idea for dcmds to do.   If I can't get space for the buffer, I won't install the patches,
  97.         and I'll beep to let them know.   Just added the     dcmdSwapWorlds to make it work
  98.         with TMon Pro. }
  99. PROCEDURE CreateZapper;
  100.  
  101. BEGIN
  102.         { Be sure that the dcmd is turned off when we start. }
  103.     SetActive (FALSE);
  104.     
  105.         { Patch the traps....  These are being patched in the world, not in the debugger world. }
  106.         { Switch over to the real world, in case the debugger does world swaps.  TMon Pro.}
  107.     dcmdSwapWorlds;
  108.  
  109.         { Use NGetTrapAddress since it is always safer on current machines.  Take the result
  110.             it gives me, and save it off in asm land, for future reference.  Then, move in the
  111.             new address of the routine, my asm glue, with stomping junk. }
  112.         { Do DisposPtr }
  113.     SetOldDisposPtr (NGetTrapAddress(_DisposPtr, OSTrap));
  114.     NSetTrapAddress(ORD(@WatchDisposPtr), _DisposPtr, OSTrap);
  115.  
  116.         { Do DisposHandle, too. }
  117.     SetOldDisposHandle (NGetTrapAddress(_DisposHandle, OSTrap));
  118.     NSetTrapAddress(ORD(@WatchDisposHandle), _DisposHandle, OSTrap);
  119.  
  120.         { Switch back to debugger world. }
  121.     dcmdSwapWorlds;
  122. END;        { CreateLeakWatcher }
  123.  
  124. {---------------------------------------------------------------------------------------------------------------------------------}
  125.     { Well, I stole this routine from MacApp utilities.  I want to lower case the strings so I 
  126.         don't have case sensitivities.  This will do it, without using the toolbox. }
  127. PROCEDURE LowerStr255(VAR s: Str255);
  128.  
  129. VAR    i:    INTEGER;
  130.  
  131. BEGIN
  132.     FOR i := 1 TO LENGTH(s) DO
  133.         IF (s[i] IN ['A'..'Z']) THEN
  134.             s[i] := CHR(Ord(s[i]) + 32)
  135. END;        { LowerStr255 }
  136.  
  137.  
  138. {---------------------------------------------------------------------------------------------------------------------------------}
  139.     { If something was not understood, dump the info for how this works. }
  140. PROCEDURE DumpHelpInfo;
  141.  
  142. BEGIN
  143.     dcmdDrawLine ('Zap  On|Off');
  144.     dcmdDrawLine ('   Zap disposed pointers/handles to $50FFC001.  (Version 2)');
  145. END;
  146.  
  147. {---------------------------------------------------------------------------------------------------------------------------------}
  148. {---------------------------------------------------------------------------------------------------------------------------------}
  149.  
  150.     { This fine fellow is the main entry point for the dcmd.  It is the hook by which I get called
  151.         by MacsBug to do my thing.  It is basically the chance to key off the command line and do
  152.         what they request. 
  153.         
  154.         Change the version number in the help, whenever it is re-released.   This is the only
  155.         version number in the program. }
  156. PROCEDURE CommandEntry (paramPtr: DCmdBlockPtr);
  157.  
  158. VAR     ch:              CHAR;
  159.                 
  160. BEGIN
  161.     CASE    paramPtr^.request OF
  162.             { When I'm called to Init, do the init code of installing the trap patches. }
  163.         dcmdInit: 
  164.                 CreateZapper;
  165.                 
  166.             { I can get various DoIt commands, so parse out the options.   If I don't get anything,
  167.                 do the standard dump info.  I lowercase the string so I can avoid any case sensitivity
  168.                 on options passed in. }
  169.         dcmdDoIt:    
  170.             BEGIN                    
  171.                 ch := dcmdGetNextParameter (pDumpString);
  172.                 LowerStr255 (pDumpString);
  173.                 IF pDumpString = 'on' THEN BEGIN
  174.                     SetActive (TRUE);
  175.                     dcmdDrawLine (' Zap is on');
  176.                 END
  177.                 ELSE  IF pDumpString = 'off' THEN BEGIN
  178.                     SetActive (FALSE);
  179.                     dcmdDrawLine (' Zap is off');
  180.                 END
  181.                 ELSE    DumpHelpInfo;
  182.             END;
  183.             
  184.             { Give them the obvious help info. }
  185.         OTHERWISE
  186.                 DumpHelpInfo;
  187.                 
  188.     END;        { End of case paramPtr^.request. }
  189.         
  190. END;    { CommandEntry }
  191.  
  192. END.
  193.